/**
 * 右键菜单管理 Composable
 * 处理右键菜单的显示、隐藏和位置计算
 * @author LYC
 * @date 2025-09-13
 */

import { ref, reactive, nextTick, readonly } from 'vue'
import type { Message } from '@/store/chat/type'

export interface ContextMenuPosition {
  x: number
  y: number
}

export interface ContextMenuState {
  visible: boolean
  position: ContextMenuPosition
  targetMessageId: string | null
  targetMessage: Message | null
}

export interface ContextMenuItem {
  id: string
  label: string
  icon?: string
  disabled?: boolean
  shortcut?: string
  divider?: boolean
  action: () => void | Promise<void>
}

/**
 * 右键菜单管理 Hook
 */
export function useContextMenu(): void {
  // 菜单状态
  const state = reactive<ContextMenuState>({
    visible: false,
    position: { x: 0, y: 0 },
    targetMessageId: null,
    targetMessage: null
  })

  // 菜单容器引用
  const menuRef = ref<HTMLElement>()

  /**
   * 计算菜单最佳位置
   */
  const calculateMenuPosition = (event: MouseEvent): ContextMenuPosition => {
    const { clientX, clientY } = event
    const { innerWidth, innerHeight } = window

    // 菜单预估尺寸（可以根据实际菜单项数量动态计算）
    const MENU_WIDTH = 200
    const MENU_HEIGHT = 300
    const PADDING = 10

    let x = clientX
    let y = clientY

    // 防止菜单超出右边界
    if (x + MENU_WIDTH > innerWidth - PADDING) {
      x = innerWidth - MENU_WIDTH - PADDING
    }

    // 防止菜单超出下边界
    if (y + MENU_HEIGHT > innerHeight - PADDING) {
      y = innerHeight - MENU_HEIGHT - PADDING
    }

    // 防止菜单超出上边界
    if (y < PADDING) {
      y = PADDING
    }

    // 防止菜单超出左边界
    if (x < PADDING) {
      x = PADDING
    }

    return { x, y }
  }

  /**
   * 显示右键菜单
   */
  const showContextMenu = async (
    event: MouseEvent,
    messageId: string,
    message: Message
  ): Promise<void> => {
    event.preventDefault()
    event.stopPropagation()

    // 设置目标消息
    state.targetMessageId = messageId
    state.targetMessage = message

    // 计算位置
    state.position = calculateMenuPosition(event)

    // 显示菜单
    state.visible = true

    // 等待DOM更新后调整位置
    await nextTick()
    adjustMenuPosition()
  }

  /**
   * 隐藏右键菜单
   */
  const hideContextMenu = (): void => {
    state.visible = false
    state.targetMessageId = null
    state.targetMessage = null
  }

  /**
   * 调整菜单位置（基于实际DOM尺寸）
   */
  const adjustMenuPosition = (): void => {
    if (!menuRef.value) return

    const menuRect = menuRef.value.getBoundingClientRect()
    const { innerWidth, innerHeight } = window
    const PADDING = 10

    let { x, y } = state.position

    // 重新计算位置以防止溢出
    if (x + menuRect.width > innerWidth - PADDING) {
      x = innerWidth - menuRect.width - PADDING
    }

    if (y + menuRect.height > innerHeight - PADDING) {
      y = innerHeight - menuRect.height - PADDING
    }

    if (x < PADDING) x = PADDING
    if (y < PADDING) y = PADDING

    state.position = { x, y }
  }

  /**
   * 处理菜单项点击
   */
  const handleMenuItemClick = async (item: ContextMenuItem): Promise<void> => {
    if (item.disabled) return

    try {
      await item.action()
    } catch (error) {
      console.error('Context menu action failed:', error)
    } finally {
      hideContextMenu()
    }
  }

  /**
   * 处理键盘事件
   */
  const handleKeydown = (event: KeyboardEvent): void => {
    if (!state.visible) return

    switch (event.key) {
      case 'Escape':
        hideContextMenu()
        break
      case 'ArrowUp':
      case 'ArrowDown':
        // TODO: 实现键盘导航
        event.preventDefault()
        break
      case 'Enter':
        // TODO: 执行当前选中的菜单项
        event.preventDefault()
        break
    }
  }

  /**
   * 处理点击外部区域
   */
  const handleClickOutside = (event: MouseEvent): void => {
    if (!state.visible || !menuRef.value) return

    const target = event.target as Element
    if (!menuRef.value.contains(target)) {
      hideContextMenu()
    }
  }

  return {
    // 状态
    state: readonly(state),
    menuRef,

    // 方法
    showContextMenu,
    hideContextMenu,
    handleMenuItemClick,
    handleKeydown,
    handleClickOutside,
    calculateMenuPosition
  }
}

/**
 * 全局右键菜单管理
 */
let globalContextMenu: ReturnType<typeof useContextMenu> | null = null

export function useGlobalContextMenu(): void {
  if (!globalContextMenu) {
    globalContextMenu = useContextMenu()
  }
  return globalContextMenu
}
